#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#include <TabLite.h>

extern unsigned int TabLiteBKDRHash(char *str);

int TabElemClearValue(TabElem* elem)
{
    switch (elem->tag)
    {
    case TAB_TAG_STR:
        if (elem->valStr != NULL)
        {
            free(elem->valStr);
            elem->valStr = NULL;
        }
        else
        {
            TabErrorSet(TAB_ERROR_FAULT);
            return -1;
        }
        break;
    case TAB_TAG_TAB:
        if (elem->valTab != NULL)
        {
            if (TabLiteDel(elem->valTab) < 0)
            {
                TabErrorSet(TAB_ERROR_FAULT);
                return -1;
            }
            elem->valTab = NULL;
        }
        else
        {
            TabErrorSet(TAB_ERROR_FAULT);
            return -1;
        }
        break;
    default:
        break;
    }
    elem->hashKey = 0;
    elem->tag = TAB_TAG_NIL;
    TabErrorSet(TAB_ERROR_OK);
    return 0;
}

static TabLite* __TabLiteRemoveKey(TabLite* tab, unsigned int hashKey)
{
    TabElem* tmp;
    ForEachTabElem(tab, tmp)
    {
        if (tmp->tag != TAB_TAG_NIL)
        {
            if (tmp->hashKey == hashKey)
            {
                if (TabElemClearValue(tmp) < 0)
                    return NULL;
                TabErrorSet(TAB_ERROR_OK);
                return tab;
            }
        }
    }
    if (!tab->next)
    {
        TabErrorSet(TAB_ERROR_NOFOUND);
        return NULL;
    }
    return __TabLiteRemoveKey(tab->next, hashKey);
}

TabLite* TabLiteRemoveByKey(TabLite* tab, char* name)
{
    if (!tab || !name)
    {
        TabErrorSet(TAB_ERROR_ARG);
        return NULL;
    }
    if (!name || !strlen(name))
    {
        TabErrorSet(TAB_ERROR_ARG);
        return NULL;
    }
    
    unsigned int hashKey = TabLiteBKDRHash(name);
    return __TabLiteRemoveKey(tab, hashKey);
}
